﻿using System;
using System.Data;
using System.Collections;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Utilities;

namespace Version3.SharePoint
{
    [CLSCompliant(false)]
    [Guid("28A66C10-6EDF-452a-B094-96958A2B42B9")]
    public class ContentLookupField : Microsoft.SharePoint.SPFieldMultiChoice
    {
        #region Declarations
        internal const string NO_CONTEXT = "NO*SP*CONTEXT";
        private string _WebURL = string.Empty;
        private string _ListName = string.Empty;
        private string _FieldOne = string.Empty;
        private string _FieldTwo = string.Empty;
        private string _FieldThree = string.Empty;
        private string _ContextID = NO_CONTEXT;
        private static System.Collections.Specialized.StringDictionary _NewColumnProperties = new System.Collections.Specialized.StringDictionary();
        #endregion

        #region Constructors
        public ContentLookupField(SPFieldCollection fields, string fieldName)
            : base(fields, fieldName)
        {
            try
            {
                _ContextID = SPContext.Current.GetHashCode().ToString();
            }
            catch
            {
                _ContextID = NO_CONTEXT;
            }
            ReadCustomProperties();
        }

        public ContentLookupField(SPFieldCollection fields, string typeName, string displayName)
            : base(fields, typeName, displayName)
        {
            try
            {
                _ContextID = SPContext.Current.GetHashCode().ToString();
            }
            catch
            {
                _ContextID = NO_CONTEXT;
            }
            ReadCustomProperties();
        }
        #endregion

        #region SPField imlementation just enough to put our UI there

        public override string GetValidatedString(object value)
        {
            return base.GetValidatedString(value);
        }

        public override BaseFieldControl FieldRenderingControl
        {
            [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
            get
            {
                BaseFieldControl fieldControl = new ContentLookupFieldControl(this);
                fieldControl.FieldName = this.InternalName;
                return fieldControl;
            }
        }

        public override void OnDeleting()
        {
            string relatedFieldName = this.RelatedField;
            if (!string.IsNullOrEmpty(relatedFieldName))
            {
                try
                {
                    this.ParentList.Fields.Delete(relatedFieldName);
                }
                catch (Exception missingFieldError)
                {
                    //Ok to ignore if the user removed the field
                    System.Diagnostics.Trace.WriteLine(missingFieldError.Message);
                }
                
            }
            base.OnDeleting();
        }

        public override void OnAdded(SPAddFieldOptions op)
        {
            Update();
            base.OnAdded(op);
        }

        public override void Update()
        {
            //we store the meta tags in a related field
            //if you create it in advance you can control its
            //form presense otherwise we assume you onlly want
            //to look it in columns and display forms
            string relatedFieldName = this.InternalName + "_MetaTAGS";
            //when adding to content types or site columns the parent list is null
            if (null != this.ParentList)
            {
                if (!this.ParentList.Fields.ContainsField(relatedFieldName))
                {
                    this.ParentList.Fields.Add(relatedFieldName, SPFieldType.Note, false);
                    SPField relatedField = this.ParentList.Fields.GetFieldByInternalName(relatedFieldName);
                    relatedField.ShowInEditForm = false;
                    relatedField.ShowInNewForm = false;
                    relatedField.Title = this.Title + " Tags";
                    relatedField.Update();
                }
            }
            this.RelatedField = relatedFieldName;
            WriteCustomProperties();
            base.Update();
        }

        #endregion

        #region Property management
        private void ReadCustomProperties()
        {
            _WebURL = WrappedGetCustomProperty("WebURL", string.Empty);
            _ListName = WrappedGetCustomProperty("ListName", string.Empty);
            _FieldOne = WrappedGetCustomProperty("FieldOne", string.Empty);
            _FieldTwo = WrappedGetCustomProperty("FieldTwo", string.Empty);
            _FieldThree = WrappedGetCustomProperty("FieldThree", string.Empty);
        }

        private void WriteCustomProperties()
        {
            this.SetCustomProperty("WebURL", this.WebURL);
            this.SetCustomProperty("ListName", this.ListName);
            this.SetCustomProperty("FieldOne", this.FieldOne);
            this.SetCustomProperty("FieldTwo", this.FieldTwo);
            this.SetCustomProperty("FieldThree", this.FieldThree);

            //Clear the new column property flags
            lock (_NewColumnProperties)
            {
                string contextKey = string.Empty;
                contextKey = _ContextID + "WebURL";
                if (_NewColumnProperties.ContainsKey(contextKey)) _NewColumnProperties.Remove(contextKey);

                contextKey = _ContextID + "ListName";
                if (_NewColumnProperties.ContainsKey(contextKey)) _NewColumnProperties.Remove(contextKey);

                contextKey = _ContextID + "FieldOne";
                if (_NewColumnProperties.ContainsKey(contextKey)) _NewColumnProperties.Remove(contextKey);

                contextKey = _ContextID + "FieldTwo";
                if (_NewColumnProperties.ContainsKey(contextKey)) _NewColumnProperties.Remove(contextKey);

                contextKey = _ContextID + "FieldThree";
                if (_NewColumnProperties.ContainsKey(contextKey)) _NewColumnProperties.Remove(contextKey);

            }


        }

        private string WrappedGetCustomProperty(string propertyName, string defaultValue)
        {
            //Since we have the static collection of pending updates
            //we need to check it first , if its not there we will
            //try to read it as a custom property
            string returnValue = string.Empty;
            lock (_NewColumnProperties)
            {
                string contextKey = _ContextID + propertyName;
                if (_NewColumnProperties.ContainsKey(contextKey))
                {
                    returnValue = _NewColumnProperties[contextKey];
                }
            }
            if (string.IsNullOrEmpty(returnValue))
            {
                try
                {
                    object sharePointCastValue = this.GetCustomProperty(propertyName);
                    returnValue = this.GetCustomProperty(propertyName) as string;
                    if (string.IsNullOrEmpty(returnValue))
                    {
                        if (null != sharePointCastValue)
                        {
                            returnValue = sharePointCastValue.ToString();
                        }
                    }
                }
                catch
                {
                    returnValue = defaultValue;
                }
            }
            if (string.IsNullOrEmpty(returnValue)) returnValue = defaultValue;
            return returnValue;
        }

        public void SetNewColumnPropertyCacheValue(string propertyKey, string propertyValue)
        {
            //Add a new string value to the static new property cache
            lock (_NewColumnProperties)
            {
                string contextKey = _ContextID + propertyKey;
                _NewColumnProperties[contextKey] = propertyValue.Trim();
            }
        }

       public string WebURL
        {
            get
            {
                lock (_NewColumnProperties)
                {
                    string contextKey = _ContextID + "WebURL";
                    if (_NewColumnProperties.ContainsKey(contextKey))
                    {
                        return _NewColumnProperties[contextKey];
                    }
                    else
                    {
                        return _WebURL;
                    }
                }
            }
            set
            {
                _WebURL = value.Trim();
            }
        }

        public string ListName
        {

            get
            {
                lock (_NewColumnProperties)
                {
                    string contextKey = _ContextID + "ListName";
                    if (_NewColumnProperties.ContainsKey(contextKey))
                    {
                        return _NewColumnProperties[contextKey];
                    }
                    else
                    {
                        return _ListName;
                    }
                }
            }
            set
            {
                _ListName = value.Trim();
            }
        }

        public string FieldOne
        {
            get
            {
                lock (_NewColumnProperties)
                {
                    string contextKey = _ContextID + "FieldOne";
                    if (_NewColumnProperties.ContainsKey(contextKey))
                    {
                        return _NewColumnProperties[contextKey];
                    }
                    else
                    {
                        return _FieldOne;
                    }
                }
            }
            set
            {
                _FieldOne = value.Trim();
            }
        }

        public string FieldTwo
        {
            get
            {
                lock (_NewColumnProperties)
                {
                    string contextKey = _ContextID + "FieldTwo";
                    if (_NewColumnProperties.ContainsKey(contextKey))
                    {
                        return _NewColumnProperties[contextKey];
                    }
                    else
                    {
                        return _FieldTwo;
                    }
                }
            }
            set
            {
                _FieldTwo = value.Trim();
            }
        }

        public string FieldThree
        {
            get
            {
                lock (_NewColumnProperties)
                {
                    string contextKey = _ContextID + "FieldThree";
                    if (_NewColumnProperties.ContainsKey(contextKey))
                    {
                        return _NewColumnProperties[contextKey];
                    }
                    else
                    {
                        return _FieldThree;
                    }
                }
            }
            set
            {
                _FieldThree = value.Trim();
            }
        }
        #endregion

    }


}


